package com.jh.user.service.impl;

import cn.jh.common.exception.ServiceException;
import cn.jh.common.pay.client.FreeQuickClient;
import cn.jh.common.pay.client.FreeQuickRequest;
import cn.jh.common.pay.client.FreeQuickResponse;
import cn.jh.common.pay.enumtype.EncryptTypeEnum;
import cn.jh.common.pay.jdpush.OrderStatus;
import cn.jh.common.pay.jdpush.PayBarException;
import cn.jh.common.pay.utils.*;
import cn.jh.common.proxy.FreeQuickProxyService;
import cn.jh.common.utils.ChannelType;
import cn.jh.common.utils.CommonConstants;
import cn.jh.common.utils.CommonsUtil;
import com.alibaba.fastjson.JSON;
import com.jh.user.business.*;
import com.jh.user.pojo.*;
import com.jh.user.pojo.enums.ChanPay;
import com.jh.user.pojo.enums.ChannelTag;
import com.jh.user.pojo.enums.PayTypeQu;
import com.jh.user.pojo.enums.UserGrade;
import com.jh.user.pojo.freeQuick.*;
import com.jh.user.repository.*;
import com.jh.user.repository.freeQuick.PassageWayRegisterRepository;
import com.jh.user.repository.freeQuick.PayBarRequestOrderRepository;
import com.jh.user.service.freeQuick.FreeQuickService;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.persistence.EntityManager;
import javax.persistence.criteria.Predicate;
import java.math.BigDecimal;
import java.util.*;
import org.apache.commons.lang3.StringUtils;

@Service
public class FreeQuickServiceImpl implements FreeQuickService{

    private Logger log = LoggerFactory.getLogger(FreeQuickServiceImpl.class);

    private JdbcTemplate jdbcTemplate;
    private PayBarRequestOrderRepository requestOrderRepository;
    private UserBankInfoRepository userBankInfoRepository;
    private PassageWayRegisterRepository passageWayRegisterRepository;
    private UserBankInfoBusiness userBankInfoBusiness;
    private UserLoginRegisterBusiness userLoginRegisterBusiness;
    private ChannelRateBusiness channelRateBusiness;
    private PassagewayBankinfoRepository passagewayBankinfoRepository;
    private BrandRateRepository brandRateRepository;
    private ChannelRateRepository channelRateRepository;
    private ChannelRepository channelRepository;
    private EntityManager entityManager;

    @Autowired
    public FreeQuickServiceImpl(JdbcTemplate jdbcTemplate,
                                PayBarRequestOrderRepository requestOrderRepository,
                                PassageWayRegisterRepository passageWayRegisterRepository,
                                UserBankInfoBusiness userBankInfoBusiness,
                                UserLoginRegisterBusiness userLoginRegisterBusiness,
                                ChannelRateBusiness channelRateBusiness,
                                PassagewayBankinfoRepository passagewayBankinfoRepository,
                                BrandRateRepository brandRateRepository,
                                ChannelRateRepository channelRateRepository,
                                ChannelRepository channelRepository,
                                EntityManager entityManager,
                                UserBankInfoRepository userBankInfoRepository) {
        this.jdbcTemplate = jdbcTemplate;
        this.requestOrderRepository = requestOrderRepository;
        this.passageWayRegisterRepository = passageWayRegisterRepository;
        this.userBankInfoBusiness = userBankInfoBusiness;
        this.userLoginRegisterBusiness = userLoginRegisterBusiness;
        this.channelRateBusiness = channelRateBusiness;
        this.passagewayBankinfoRepository = passagewayBankinfoRepository;
        this.brandRateRepository = brandRateRepository;
        this.channelRateRepository = channelRateRepository;
        this.channelRepository = channelRepository;
        this.entityManager = entityManager;
        this.userBankInfoRepository = userBankInfoRepository;
    }
    /**
     * 查询商户是否注册
     * @param entity
     * @return
     */
   public PassageWayRegister queryRegisterMerchant(PassageWayRegister entity){
       PassageWayRegister register = passageWayRegisterRepository.findByUserIdAndChannelProductCode(entity.getUserId(),entity.getChannelProductCode());
       long userId = Long.valueOf(entity.getUserId()).longValue();
       UserBankInfo bankInfo = userBankInfoRepository.findByUserIdAndCardTypeAndIdDef(userId, CardType.DEBIT.getDesc(),"1");
       if (null == bankInfo) {
           throw new PayBarException("无可用借记卡信息！");
       }
       register.addMap(bankInfo);
       return register;
   }

   private PassageWayRegister queryRegister(PassageWayRegister wayRegister, String channelProductCode) throws ServiceException {
       String userIdStr = wayRegister.getUserId();
       long userId = Long.parseLong(userIdStr);
       PassageWayRegister register = passageWayRegisterRepository.findByUserIdAndChannelProductCode(userIdStr, channelProductCode);
       if (null == register) {
           // 未注册，进行注册
           throw new ServiceException("您还未注册该通道！");
       }
       UserBankInfo bankInfo = userBankInfoRepository.findByUserIdAndCardTypeAndIdDef(userId, CardType.DEBIT.getDesc(),"1");
       if (null == bankInfo) {
           throw new ServiceException("无可用借记卡信息！");
       }
       register.addMap(bankInfo);
       return register;
   }

    /**
     * 畅捷商户注册接口
     * @param entity
     * @return
     * @throws PayBarException
     */
    @Transactional
    public Map registerMerchant(PassageWayRegister entity, String userId) throws ServiceException {
        Map map = new HashMap();
        String url = CommonConstants.BASEURL+ CommonConstants.REGISTER_MERCHANT;
        //查询结算卡
        UserBankInfo card = userBankInfoBusiness.findUserBankInfoByUseridAndIdDef(Integer.valueOf(userId),"1","2");
        ChannelRate channelRate = channelRateBusiness.findChannelRateByUserid(Integer.valueOf(userId),Integer.valueOf(entity.getChannelProductCode()));
        User user = userLoginRegisterBusiness.findUserById(Integer.valueOf(userId));
        //查询用户信息
        if (null == channelRate) {
            //保存个人费率信息
            saveChannelRate(entity, user.getGrade(), user.getBrandId());
        }
        channelRate = channelRateBusiness.findChannelRateByUserid(Integer.valueOf(userId),Integer.valueOf(entity.getChannelProductCode()));

        String merchantNo = String.valueOf(System.currentTimeMillis());
        String requestNo = String.valueOf(System.currentTimeMillis());
        entity.setRequestNo(requestNo);
        entity.setMerchantNo(merchantNo);

        FreeQuickRequest freeQuickRequest = entity.transform(user,card,channelRate);
        log.debug("freeQuickRequest:" + freeQuickRequest.toString());
        FreeQuickResponse response = FreeQuickClient.post(url, freeQuickRequest);
        Map<String, String> resp = response.getResultMap();
        if (null == resp) {
            log.info("畅捷商户注册接口registerMerchant : " + response.toString());
            throw new ServiceException(response.getMessage());
        }
        String codeVal = resp.getOrDefault("code", "0");
        String bizCode = resp.getOrDefault("bizCode", "0");
        String channelMerchantNo = resp.getOrDefault("merchantNo", "0");
        entity.setRequestNo(channelMerchantNo);
        resp.put("requestNo",requestNo);
        resp.put("card",card.toString());
        resp.put("user",user.toString());
        resp.put("channelRate",channelRate.toString());
        log.debug("apiResponse:" + JSON.toJSONString(response));
        if(codeVal.equals(CommonConstants.FREE_SUCCESS)){
            //保存数据
            entity.setEncryptKey(response.getEncryptKey());
            //注册成功新增数据到注册表
            entity.setBankStatus("0");
            entity.setWithdrawDepositRate(new BigDecimal("3.00"));
            entity.setRegisterState("1");//注册成功
            try {
                if(bizCode.equals("1")){
                    entity = passageWayRegisterRepository.saveAndFlush(entity);
                }
            } catch (RuntimeException e) {
                log.info("保存通道注册表异常" + e.getMessage());
                throw new ServiceException("保存通道注册表失败！");
            }
        }
        map.put("id",entity.getId());
        return map;
    }

    /**
     * 保存个人费率信息
     * @param entity
     * @param grade
     * @param brandId
     * @throws ServiceException
     */
    @Transactional
    public void saveChannelRate(PassageWayRegister entity, String grade, long brandId) throws ServiceException {
        try {
            if (null == entity) {
                throw new ServiceException("商户注册信息为空！");
            }
            String channelId = entity.getChannelProductCode();

            List<BrandRate> brandRateList = brandRateRepository.getBrandRateByChannelIdAndGrand(Long.parseLong(channelId), UserGrade.of(Short.parseShort(grade)), brandId);
            if (null == brandRateList || brandRateList.size() == 0) {
                throw new ServiceException("无公共费率信息！");
            }
            List<ChannelRate> list = new ArrayList<>();
            for (BrandRate br : brandRateList) {
                ChannelRate channelRate = new ChannelRate();
                channelRate.setUserId(Long.parseLong(entity.getUserId()));
                channelRate.setBrandId(brandId);
                channelRate.setChannelId(Long.parseLong(entity.getChannelProductCode()));
                channelRate.setRate(br.getRate());
                channelRate.setExtraFee(br.getExtraFee());
                channelRate.setGradeRate(br.getGradeRate());
                channelRate.setStatus(br.getStatus());
                channelRate.setPayType(br.getPayType());
                channelRate.setBrandRate(br.getBrandRate());
                channelRate.setUpdateTime(Calendar.getInstance().getTime());
                channelRate.setCreateTime(Calendar.getInstance().getTime());
                list.add(channelRate);
            }
            List<ChannelRate> channelRateList = channelRateRepository.save(list);
            log.info("保存个人费率信息结果：channelRateList = {}", channelRateList.toString());
        } catch (RuntimeException e) {
            log.error("保存个人费率信息saveChannelRate异常" + e.getMessage());
            throw new ServiceException(e.getMessage());
        }
    }


    /**
     * 商户开通产品
     * @param entity
     * @return
     */
    @Transactional
    public Map registerProduct(PassageWayRegister entity, long userId) throws ServiceException{
        String url = CommonConstants.BASEURL + CommonConstants.REGISTER_MERCHANT_PRODUCT;
        FreeQuickRequest request = new FreeQuickRequest(CommonConstants.AGENT_NO, CommonConstants.AGENT_KEY);
        request.setSupportSign(false);
        ChannelRate channelRate = channelRateBusiness.findChannelRateByUserid(Integer.valueOf(entity.getUserId()),Integer.valueOf(entity.getChannelProductCode()));
        String rate = String.valueOf(channelRate.getRate());
        String channleName = ChannelType.of(Integer.valueOf(entity.getChannelProductCode())).getValue();
        request.setEncryptType(EncryptTypeEnum.AES);
        request.addParam("merchantNo", entity.getRequestNo());
        request.addParam("channelProductCode", channleName);
        request.addParam("debitRate",rate);
        request.addParam("creditRate", rate);
        request.addParam("debitCapAmount", "");
        request.addParam("creditCapAmount", "");
        entity.setDebitRate(channelRate.getRate());
        entity.setCreditRate(channelRate.getRate());
        entity.setChannelProductCode(entity.getChannelProductCode());
        log.info("request:" + request.toString());
        FreeQuickResponse response = FreeQuickClient.post(url, request);
        Map<String, String> param = response.getResultMap();
        log.info("response:" + JSON.toJSONString(response));
        String code = param.getOrDefault("code","0");
        String bizCode = param.getOrDefault("bizCode","0");
        String binkMsg = param.getOrDefault(bizCode,"0");
        if(!code.equals(CommonConstants.FREE_SUCCESS)){
            param.put("binkMsg",binkMsg);
            param.put("requestNo",entity.getRequestNo());
            param.put("merchantNo",entity.getChannelMerchantNo());
            return param;
        }
        entity.setRegisterState("1");
        entity.setUserId(userId + "");
        //保存数据
        passageWayRegisterRepository.save(entity);
        param.put("requestNo",entity.getRequestNo());
        param.put("merchantNo",entity.getChannelMerchantNo());
        return param;
    }

    @Transactional
    public void saveUserAccount(UserAccount account){
        String sql = "update t_user_account set t_user_account.rebate_balance = " + account.getRebateBalance() + " where id = " + account.getId();
        jdbcTemplate.update(sql);

    }


    /**
     * 绑卡
     */
    @Override
    @Transactional
    public Map bindCard(UserBankInfo card,String merchantNo,int channelid,int id) throws PayBarException{
        PassagewayBankInfo info = new PassagewayBankInfo();
        String url = CommonConstants.BASEURL + CommonConstants.BIND_CARD;
        FreeQuickRequest request = new FreeQuickRequest(CommonConstants.AGENT_NO, CommonConstants.AGENT_KEY);
        String channelTag = ChannelType.of(channelid).getValue();

        String requestN = String.valueOf(System.currentTimeMillis());
        request.setSupportSign(false);
        request.setEncryptType(EncryptTypeEnum.AES);
        if(id > 0){
            info.setId(id);
        }
        info.setUserId(card.getUserId());
        info.setBankAbbr(card.getBankAbbr());
        info.setBankAccountName(card.getUserName());
        info.setBankCardNo(card.getCardNo());
        info.setBankMobile(card.getPhone());
        info.setCardType(card.getCardType());
        info.setCertNo(card.getIdcard());
        info.setChannelProductCode(channelid+"");
        info.setCvn2(card.getSecurityCode());
        info.setExpired(card.getExpiredTime());
        info.setRequestNo(requestN);
        info.setMerchantNo(merchantNo);
        String cardType = card.getCardType();
        if (cardType.equals("0")) {
            cardType = "CREDIT";
        }
        if (cardType.equals("2")) {
            cardType = "DEBIT";
        }
        request.addParam("requestNo", requestN);
        request.addParam("merchantNo", merchantNo);
        request.addParam("channelProductCode", channelTag);
        request.addParam("bankCardNo", card.getCardNo());
        request.addParam("bankAccountName", card.getUserName());//银行卡开户名
        request.addParam("cardType", cardType);
        request.addParam("bankMobile", card.getPhone());
        request.addParam("certType", CommonConstants.CRAD_TYPE);
        request.addParam("certNo", card.getIdcard());
        request.addParam("cvn2", card.getSecurityCode());
        request.addParam("expired", card.getExpiredTime());
        request.addParam("busiType ", "");
        request.addParam("bankAbbr", card.getBankAbbr());
        request.addParam("serverCallbackUrl", "http://47.104.158.3:8080/v1.0/user/callback/bindCard");
        request.addParam("webCallbackUrl","http://47.104.158.3:8080/v1.0/user/callback/bindCard");
        //调用畅捷绑卡接口
        log.info("调用畅捷绑卡接口request:" + request.toString());
        FreeQuickResponse response = FreeQuickClient.post(url, request);
        Map<String, String> param = response.getResultMap();
        log.info("调用畅捷绑卡接口response:" + JSON.toJSONString(response));
        String code = param.getOrDefault("code","0");
        String bizCode =  param.getOrDefault("bizCode","0");
        String binkMsg =  param.getOrDefault("binkMsg","0");
        String bindStatus = param.getOrDefault("bindStatus","0");
        param.put("binkCode",bizCode);
        param.put("binkMsg",binkMsg);
        param.put("bindStatus",bindStatus);
        param.put("cardNo",card.getCardNo());
        String status = "0" ;

        info.setBinkCode(bizCode);
        info.setBinkMsg(binkMsg);
        info.setUpdateTime(Calendar.getInstance().getTime());
        if(code.equals(CommonConstants.FREE_SUCCESS)){
            PassagewayBankInfo infos = passagewayBankinfoRepository.findPassagewayBankInfoByBankCardNo(card.getCardNo(),String.valueOf(channelid));
            if(bindStatus.equalsIgnoreCase(CommonConstants.PENDING)){
                if (infos != null) {
                    String sql1 = "update t_bank_info set request_no = " + requestN + " where card_no = " + card.getCardNo();
                    jdbcTemplate.update(sql1);
                }
            }else if(bindStatus.equalsIgnoreCase(CommonConstants.FAIL)){
                status = "3";
            }else if(bindStatus.equalsIgnoreCase(CommonConstants.BASE_SUCCESS)){
                status = "1";
            }

            if(StringUtils.isNotBlank(status)){
                String sql = "update t_passage_way_register set bank_status = " + status + " where request_no = " + merchantNo;
                jdbcTemplate.update(sql);
            }
            info.setChannelProductCode(String.valueOf(channelid));
            info.setBindStatus(status);
            passagewayBankinfoRepository.save(info);
            return param;
        }else{
            info.setBindStatus(status);
            passagewayBankinfoRepository.save(info);
            return param;
        }
    }

    public PassagewayBankInfo queryBankInfoAndChannelProductCode(String bankCardNo,String channelProductCode){
        return passagewayBankinfoRepository.findPassagewayBankInfoByBankCardNo(bankCardNo,channelProductCode);
    }

    /**
     * 畅捷提交短信验证
     * @param smsCode
     */
    @Transactional
    public Map bindCardConfirm(String smsCode,long userId,String bankCode) throws ServiceException {
        PassageWayRegister register = passageWayRegisterRepository.findFirstByUserId(String.valueOf(userId));
        UserBankInfo info = userBankInfoBusiness.findUserBankInfoByCardNo(bankCode);

        if(register == null){
            if (log.isDebugEnabled()) {
                throw new ServiceException("该商户未注册通道");
            }
        }
        String merchantNo = register.getRequestNo();
        String url = CommonConstants.BASEURL + CommonConstants.CONFIRM_BIND_CARD;
        FreeQuickRequest request = new FreeQuickRequest(CommonConstants.AGENT_NO, CommonConstants.AGENT_KEY);
        request.setSupportSign(false);
        request.setEncryptType(EncryptTypeEnum.AES);
        request.addParam("bindRequestNo", info.getRequestNo());
        request.addParam("merchantNo", merchantNo);
        request.addParam("smsCode", smsCode);

        log.debug("request:" + request.toString());
        FreeQuickResponse response = FreeQuickClient.post(url, request);
        String code1 = response.getCode();
        String result = CommonsUtil.freeQuickError(code1);
        if (!"0".equals(result)) {
            throw new ServiceException(result);
        }

        Map<String, String> param = response.getResultMap();
        log.info("畅捷提交短信验证返回response:" + JSON.toJSONString(response));
        String code = param.getOrDefault("code","0");
        String bizCode = param.getOrDefault("bizCode","0");
        if (code.equalsIgnoreCase(CommonConstants.FREE_SUCCESS )
                || bizCode.toUpperCase().equals("PB0200002".toUpperCase())) {
            String sql = "update t_passageway_bank_info set bind_status = 1 where bank_card_no = " + bankCode;
            jdbcTemplate.update(sql);
        }
        return param;
    }

    @Transactional
    public PayBarRequestOrder processBindCardNotify(BindCardNotify notify) throws PayBarException {
        PayBarRequestOrder requestOrder = requestOrderRepository.findByRequestNoAndMerchantNo(
                notify.getRequestNo(), notify.getMerchantNo());
        if (requestOrder == null) {
            throw new PayBarException("请求信息不存在，商户号[" + notify.getMerchantNo() + "]请求单号[" + notify.getRequestNo() + "]");
        }
        requestOrder.setStatus(OrderStatus.of(notify.getBindStatus()));
        requestOrder.setRemark(notify.getContent());
        requestOrderRepository.saveAndFlush(requestOrder);
        return requestOrder;
    }


    @Transactional
    public PassageWayRegister processPayNotify(BindCardNotify notify) throws PayBarException {
        PassageWayRegister order = passageWayRegisterRepository.findAllByRequestNoAndMerchantNo(notify.getMerchantNo(), notify.getRequestNo());
        if (order == null) {
            throw new PayBarException("用户不存在，商户号[" + notify.getMerchantNo() + "]请求单号[" + notify.getRequestNo() + "]");
        }

        // 订单状态和异步请求的状态一致，没有必要处理
        if (notify.getBindStatus() == order.getRegisterState()) {
            return order;
        }
        order.setRegisterState("1");
        passageWayRegisterRepository.save(order);
        return order;
    }



    public Map modifyMerchantFeeInfo(String requestNo,String merchantNo,String channelProductCode,String cardType,String bizType,String feeValue) throws ServiceException {
        PayBarRequest request = new PayBarRequest(CommonConstants.AGENT_NO, CommonConstants.AGENT_KEY);
        request.setSupportSign(false);
        request.setEncryptType(EncryptType.AES);
        request.addParam("channelProductCode", channelProductCode);//通道产品
        request.addParam("merchantNo", merchantNo);//商户id
        request.addParam("cardType", cardType);//卡类型
        request.addParam("bizType", bizType);//费类型
        request.addParam("feeValue", feeValue);//费率
        request.addParam("capAmount", "");//封顶金额
        log.debug("response:" + request.toString());
        PayBarResponse response = PayBarClient.post(CommonConstants.BASEURL+ CommonConstants.MODIFY_MERCHANT_FEE, request);
        log.debug("response:" + JSON.toJSONString(response));
        Map<String, String> resp = response.getResultMap();
        return resp;
    }

    @Override
    public Map<String, String> queryMerchantFeeInfo(String merchantNo) throws ServiceException {
        List<PassageWayRegister> registerList = passageWayRegisterRepository.findByMerchantNo(merchantNo);
        if (null == registerList || registerList.size() == 0) {
            throw new ServiceException("无注册通道的商户信息！");
        }

        String requestNo = registerList.get(0).getRequestNo();
        Map<String, String> resMap = FreeQuickProxyService.queryMerchantFeeInfo(requestNo);
        if (null == resMap) {
            return CommonsUtil.returnError("查询商户查询费率信息接口请求失败，请稍后再试！");
        }
        String bizCode = resMap.get("bizCode");
        String code = resMap.get("code");
        if (CommonConstants.BRAND_OTHER.equals(bizCode) && CommonConstants.FREE_SUCCESS.equals(code) ) {
            // 操作成功
            String feeReponseList = resMap.get("feeReponseList");
            JSONArray jsonArray = JSONArray.fromObject(feeReponseList);
            JSONArray array = new JSONArray();
            if (null != jsonArray && jsonArray.size() > 0) {
                for (int i = 0; i < jsonArray.size(); i++) {
                    JSONObject jsonObj = new JSONObject();
                    Object o = jsonArray.get(i);
                    JSONObject jsonObject = JSONObject.fromObject(o);
                    String bizType = jsonObject.getString("bizType");
                    String cardType = jsonObject.getString("cardType");
                    jsonObj.accumulate("cardType", com.jh.user.pojo.enums.CardType.of(cardType).getDesc());
                    String status = jsonObject.getString("status");
                    jsonObj.accumulate("status", com.jh.user.pojo.enums.RegisterStatus.of(status).getDesc());

                    String capAmount = jsonObject.getString("capAmount");
                    jsonObj.accumulate("capAmount", capAmount);

                    jsonObj.accumulate("bizType", PayTypeQu.of(bizType).getDesc());
                    if (PayTypeQu.TRADE.getValue().equals(bizType)) {
                        // 交易
                        jsonObj.accumulate("feeValue", jsonObject.getString("feeValue"));
                        jsonObj.accumulate("channelProductCode", jsonObject.getString("channelProductCode"));
                        jsonObj.accumulate("channelProductCodeCN", ChannelTag.of(jsonObject.getString("channelProductCode")).getDesc());
                    } else {
                        jsonObj.accumulate("feeValue", "");
                        jsonObj.accumulate("channelProductCode", "");
                        jsonObj.accumulate("channelProductCodeCN", "");
                    }

                    array.add(jsonObj);
                }
            }
            return com.jh.user.util.CommonsUtil.returnSuccess(array, "成功！");
        } else {
            // 失败
            String bizMsg = resMap.get("bizMsg");
            log.info("商户查询费率信息接口返回：bizCode={}，bizMsg={}", bizCode, bizMsg);
            return CommonsUtil.returnError(bizMsg);
        }
    }

    @Override
    public Map<String, Object> queryMerchantFeeInfoList(String merchantNo, String merchantName, String pwrStatus, String bindMobile, Pageable pageable) {
        List<Map<String, Object>> list = new ArrayList<>();
        Specification<PassageWayRegister> spec = (root, criteriaQuery, criteriaBuilder) -> {
            List<Predicate> predicates = new ArrayList<>();
            if (StringUtils.isNotEmpty(merchantNo)) {
                predicates.add(criteriaBuilder.equal(root.<String>get("merchantNo"), merchantNo));
            }
            if (StringUtils.isNotEmpty(merchantName)) {
                predicates.add(criteriaBuilder.equal(root.<String>get("merchantName"), merchantName));
            }
            if (StringUtils.isNotEmpty(pwrStatus)) {
                predicates.add(criteriaBuilder.equal(root.<String>get("pwrStatus"), pwrStatus));
            }
            if (StringUtils.isNotEmpty(bindMobile)) {
                predicates.add(criteriaBuilder.equal(root.<String>get("bindMobile"), bindMobile));
            }
            return criteriaQuery.where(predicates.toArray(new Predicate[0])).getRestriction();
        };

        Page<PassageWayRegister> wayRegisterPage = passageWayRegisterRepository.findAll(spec, pageable);

        // 封装数据，去除不必要的数据
        long totalElements = wayRegisterPage.getTotalElements();
        int totalPages = wayRegisterPage.getTotalPages();
        int number = wayRegisterPage.getNumber();
        int numberOfElements = wayRegisterPage.getNumberOfElements();
        int size = wayRegisterPage.getSize();
        Sort sort = wayRegisterPage.getSort();

        Map<String, Object> out = new HashMap<>();
        out.put("totalElements", totalElements);
        out.put("totalPages", totalPages);
        out.put("number", number);
        out.put("numberOfElements", numberOfElements);
        out.put("size", size);
        out.put("sort", sort);

        List<PassageWayRegister> content = wayRegisterPage.getContent();
        if (null != content && content.size() > 0) {
            for (PassageWayRegister wayRegister : content) {
                String existMerchantNo = wayRegister.getMerchantNo();
                String existMerchantName = wayRegister.getMerchantName();
                String existPwrStatus = wayRegister.getPwrStatus();
                String existBindMobile = wayRegister.getBindMobile();
                String channelProductCode = wayRegister.getChannelProductCode();

                Map<String, Object> map = new HashMap<>();
                map.put("merchantNo", existMerchantNo);
                map.put("merchantName", existMerchantName);
                map.put("pwrStatus", existPwrStatus);
                map.put("bindMobile", existBindMobile);
                map.put("channelProductCode", ChanPay.of(channelProductCode));

                list.add(map);
            }
        }

        out.put("content", list);
        return out;
    }

    @Override
    @Transactional
    public Map<String, String> modifyMerchantSettlementInfo(String lineNo, String province, String city, String phone, String bankBranchName, String cardType,
                                                            String bankName, String userName, String abbreviation, long userId, String beforeCardNo,
                                                            String cardNo, String securityCode, String expiredTime) throws ServiceException {
        Map<String, String> resMap = new HashMap<>();
        try {
            // 1、获取商户号
            List<PassageWayRegister> list = passageWayRegisterRepository.findByUserId(String.valueOf(userId));
            if (list.size() == 0) {
                throw new ServiceException("未查询到商户信息！");
            }
            String requestNo = "";
            for (PassageWayRegister passageWayRegister : list) {
                requestNo = passageWayRegister.getRequestNo();
                break;
            }

            // 2、商户修改结算卡信息
            resMap = FreeQuickProxyService.modifyMerchantSettlementInfo(requestNo, phone, cardNo, userName,
                    bankName, bankBranchName, abbreviation, lineNo, province, city);
            if (null == resMap) {
                throw new ServiceException("修改商户结算卡信息失败，请稍后再试！");
            }

            String bizCode = resMap.get("bizCode");
            String code = resMap.get("code");
            String bizMsg = resMap.get("bizMsg");
            if (!"1".equals(bizCode) || !"200".equals(code)) {
                // 失败
                log.info("修改商户结算卡信息接口返回：bizCode={}，bizMsg={}", bizCode, bizMsg);
                throw new ServiceException(bizMsg);
            }

            // 3、更新t_passageway_bank_info表中被修改结算卡信息
            PassagewayBankInfo beforeBankInfo = passagewayBankinfoRepository.findUsablePassagewayBankInfoByBankCardNo(beforeCardNo);
            if (null == beforeBankInfo) {
                log.info("结算卡" + beforeCardNo + "已经解绑！！！");
            }
            beforeBankInfo.setBindStatus("0");

            beforeBankInfo = passagewayBankinfoRepository.save(beforeBankInfo);

            String channelProductCode = beforeBankInfo.getChannelProductCode();
            String merchantNo = beforeBankInfo.getMerchantNo();
            String certNo = beforeBankInfo.getCertNo();

            // 4、将新的结算卡信息保存到t_passageway_bank_info表中
            PassagewayBankInfo afterBankInfo = passagewayBankinfoRepository.findPassagewayBankInfoByBankCardNo(cardNo,beforeBankInfo.getChannelProductCode());
            if (null == afterBankInfo) {
                // 表中无信息，新增
                PassagewayBankInfo pb = new PassagewayBankInfo();
                pb.setUserId(userId);
                pb.setChannelProductCode(channelProductCode);
                pb.setRequestNo(String.valueOf(System.currentTimeMillis()));
                pb.setMerchantNo(merchantNo);
                pb.setBankCardNo(cardNo);
                pb.setBankAccountName(userName);
                pb.setCardType(cardType);
                pb.setBankMobile(phone);
                pb.setCertNo(certNo);
                pb.setCvn2(securityCode);
                pb.setExpired(expiredTime);
                pb.setBankAbbr(lineNo.substring(0, 3));
                pb.setBinkCode(bizCode);
                pb.setBinkMsg(bizMsg);
                pb.setBindStatus("1");
                pb.setCreateTime(Calendar.getInstance().getTime());
                pb.setUpdateTime(Calendar.getInstance().getTime());
                passagewayBankinfoRepository.save(pb);
            } else {
                // 表中有信息，更新
                afterBankInfo.setBindStatus("1");
                afterBankInfo.setUpdateTime(Calendar.getInstance().getTime());
                passagewayBankinfoRepository.save(afterBankInfo);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return resMap;
    }

    @Override
    public JSONArray queryBankCardList(String merchantNo, String channelProductCode) throws ServiceException {
        Map<String, String> resMap;
        try {
            if (StringUtils.isEmpty(merchantNo)) {
                throw new ServiceException("商户号为空！");
            }
            List<PassageWayRegister> registerList = passageWayRegisterRepository.findByMerchantNo(merchantNo);
            if (null == registerList || registerList.size() == 0) {
                throw new ServiceException("未查询到通道注册信息，请确认商户号是否正确！");
            }
            String requestNo = registerList.get(0).getRequestNo();
            resMap = FreeQuickProxyService.queryBankCardList(requestNo, channelProductCode);
            log.info(merchantNo + "商户已绑定的所有银行卡列表resMap={}", resMap);
            String bizCode = resMap.get("bizCode");
            String bizMsg = resMap.get("bizMsg");
            String code = resMap.get("code");
            if (!"1".equals(bizCode) || !"200".equals(code)) {
                // 失败
                throw new ServiceException(bizMsg);
            }
            String bankCardNoList = resMap.get("bankCardNoList");
            JSONArray jsonArray = JSONArray.fromObject(bankCardNoList);
            return jsonArray;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    @Override
    public Map<String, String> queryMerchantWallet(String merchantNo) throws ServiceException {
        Map<String, String> resMap = new HashMap<>();
        try {
            List<PassageWayRegister> registerList = passageWayRegisterRepository.findByMerchantNo(merchantNo);
            if (null == registerList) {
                throw new ServiceException("未查询到通道注册信息，请确认商户号是否正确！");
            }
            String requestNo = registerList.get(0).getRequestNo();
            resMap = FreeQuickProxyService.queryMerchantWallet(requestNo);
            String bizCode = resMap.get("bizCode");
            String bizMsg = resMap.get("bizMsg");
            String code = resMap.get("code");
            if (!"1".equals(bizCode) || !"200".equals(code)) {
                // 失败
                throw new ServiceException(bizMsg);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return resMap;
    }

    @Override
    @Transactional
    public Map<String, String> modifyMerchantFeeInfoo(String merchantNo, String channelProductCode, String cardType, String bizType,
                                                      BigDecimal feeValue, BigDecimal capAmount) throws ServiceException {
        // 1、获取通道信息
        Channel channel = channelRepository.findByChannelTag(channelProductCode);
        if (null == channel) {
            throw new ServiceException("未获取到通道信息，请检查通道产品是否正确！");
        }
        String channelNo = channel.getChannelNo();

        PassageWayRegister byMerchantNo = passageWayRegisterRepository.findByMerchantNoAndChannelProductCode(merchantNo, channelNo);
        if (null == byMerchantNo) {
            throw new ServiceException("未查询到通道注册信息，请确认商户号是否正确！");
        }
        String userId = byMerchantNo.getUserId();
        String requestNo = byMerchantNo.getRequestNo();

        if ("TRADE".equals(bizType)) {   // 交易，修改的是费率
            // 2、获取交易类型为1的个人费率信息
            ChannelRate channelRate = channelRateRepository.findChannelRate(Long.parseLong(userId), 407, Long.parseLong(channelNo), (short) 1);
            if (null == channelRate) {
                // 无个人费率信息，直接修改上游通道费率
                log.info("{}商户无个人费率信息，直接修改上游通道费率（交易）", merchantNo);
            } else {
                // 3、更新个人费率
                BigDecimal rate = channelRate.getRate();
                channelRate.setRate(feeValue);
                channelRate.setUpdateTime(Calendar.getInstance().getTime());
                channelRateRepository.save(channelRate);
                log.info("商户{}修改前的个人费率：{}，修改后的个人费率：{}",merchantNo, rate, feeValue);
            }

            // 4、更新商户注册表中相应卡的费率
            if (CommonConstants.CREDIT_0.equals(cardType)) {
                // 更新贷记卡费率
                BigDecimal creditRate = byMerchantNo.getCreditRate();
                byMerchantNo.setCreditRate(feeValue);
                passageWayRegisterRepository.save(byMerchantNo);
                log.info("{}商户的商户注册表中修改前的贷记卡费率：{}，修改后的贷记卡费率：{}", merchantNo, creditRate, feeValue);
            }
            if (CommonConstants.DEBIT_2.equals(cardType)) {
                // 更新借记卡费率
                BigDecimal debitRate = byMerchantNo.getDebitRate();
                byMerchantNo.setDebitRate(feeValue);
                passageWayRegisterRepository.save(byMerchantNo);
                log.info("{}商户的商户注册表中修改前的借记卡费率：{}，修改后的借记卡费率：{}", merchantNo, debitRate, feeValue);
            }
        } else {   // 提现，修改的是手续费
            ChannelRate channelRate = channelRateRepository.findChannelRate(Long.parseLong(userId), 407, Long.parseLong(channelNo), (short) 2);
            if (null == channelRate) {
                // 无个人费率信息，直接修改上游通道费率
                log.info("{}商户无个人费率信息，直接修改上游通道费率（提现）", merchantNo);
            } else {
                // 2、更新个人体现费
                BigDecimal extraFee = channelRate.getExtraFee();
                channelRate.setExtraFee(feeValue);
                channelRate.setUpdateTime(Calendar.getInstance().getTime());
                channelRateRepository.save(channelRate);
                log.info("商户{}修改前的个人提现费用：{}，修改后的个人提现费用：{}",merchantNo, extraFee, feeValue);
            }

            // 3、更新商户注册表中借记卡提现手续费
            List<PassageWayRegister> registerList = passageWayRegisterRepository.findByMerchantNo(merchantNo);
            for (PassageWayRegister register : registerList) {
                register.setWithdrawDepositSingleFee(feeValue);
            }
//            BigDecimal withdrawDepositSingleFee = byMerchantNo.getWithdrawDepositSingleFee();
//            byMerchantNo.setWithdrawDepositSingleFee(feeValue);
//            passageWayRegisterRepository.save(byMerchantNo);
            passageWayRegisterRepository.save(registerList);
            log.info("{}商户的商户注册表中，修改后的提现手续费：{}", merchantNo, feeValue);
        }

        // 最后一步
        Map<String, String> resMap = FreeQuickProxyService.modifyMerchantFeeInfo(requestNo, channelProductCode, cardType, bizType, feeValue.toString(), "");
        log.info("商户修改产品费率：代理商通过该接口可修改已开通的产品费率信息结果：{}", resMap.toString());
        String bizCode = resMap.get("bizCode");
        String bizMsg = resMap.get("bizMsg");
        String code = resMap.get("code");
        if (!"1".equals(bizCode) || !"200".equals(code)) {
            // 失败
            throw new ServiceException(bizMsg);
        }
        entityManager.flush();
        return resMap;
    }

    @Override
    public Map<String, Object> getMerchantInfo(String merchantNo, String channelProductCode) throws ServiceException {
        Map<String, Object> map = new HashMap<>();

        List<PassageWayRegister> byMerchantNo = passageWayRegisterRepository.findByMerchantNo(merchantNo);
        if (null == byMerchantNo || byMerchantNo.size() == 0) {
            throw new ServiceException("无此商户信息！");
        }
        PassageWayRegister passageWayRegister = byMerchantNo.get(0);

        String merchantName = passageWayRegister.getMerchantName();
        String registerState = passageWayRegister.getRegisterState();
        String idCardNo = passageWayRegister.getIdCardNo();
        String userId = passageWayRegister.getUserId();

        if ("1".equals(registerState)) {
            registerState = "已注册";
        } else {
            registerState = "未注册";
        }
        String bindMobile = passageWayRegister.getBindMobile();
        String createTime = passageWayRegister.getCreateTime();

        map.put("userId", userId);
        map.put("merchantName", merchantName);
        map.put("registerState", registerState);
        map.put("bindMobile", bindMobile);
        map.put("createTime", createTime);

        Map<String, String> res = FreeQuickProxyService.queryMerchantInfo(idCardNo, channelProductCode);
        if (null == res) {
            throw new ServiceException("查询商户信息失败，请稍后再试！");
        }

        String bizCode = res.get("bizCode");
        String code = res.get("code");
        String bizMsg = res.get("bizMsg");
        if (!"1".equals(bizCode) || !"200".equals(code)) {
            // 失败
            log.info("查询商户信息接口返回：bizCode={}，bizMsg={}", bizCode, bizMsg);
            throw new ServiceException(bizMsg);
        }
        String channelCode = res.get("channelCode");
        String encryptKey = res.get("encryptKey");
        String settleBankAccountName = res.get("settleBankAccountName");

        map.put("channelCode", channelCode);
        map.put("encryptKey", encryptKey);
        map.put("settleBankAccountName", settleBankAccountName);
        return map;
    }

    @Override
    public Map<String, String> queryMerchantInfo(String idCard, String channelProductCode) throws ServiceException {
        Map<String, String> res = FreeQuickProxyService.queryMerchantInfo(idCard, channelProductCode);
        if (null == res) {
            throw new ServiceException("查询商户信息失败，请稍后再试！");
        }

        String bizCode = res.get("bizCode");
        String code = res.get("code");
        String bizMsg = res.get("bizMsg");
        if (!"1".equals(bizCode) || !"200".equals(code)) {
            // 失败
            log.info("查询商户信息接口返回：bizCode={}，bizMsg={}", bizCode, bizMsg);
            throw new ServiceException(bizMsg);
        }
        return res;
    }

    @Override
    public Map<String, String> queryMerchantNo(String merchantNo) throws ServiceException {
        Map<String, String> res = new HashMap<>();

        List<PassageWayRegister> registerList = passageWayRegisterRepository.findByMerchantNo(merchantNo);
        if (null == registerList || registerList.size() == 0) {
            throw new ServiceException("未查询到该商户注册信息，请确认商户编号是否正确！");
        }
        PassageWayRegister passageWayRegister = registerList.get(0);
        merchantNo = passageWayRegister.getRequestNo();

        res.put("merchantNo", merchantNo);
        return res;
    }
}
